package com.pengshun.modules.api.transport.service.impl;

import com.pengshun.modules.api.coal.repository.UserRepository;
import com.pengshun.modules.api.coal.util.CommonUtil;
import com.pengshun.modules.api.mapper.TransportMapper;
import com.pengshun.modules.api.transport.dto.InfoDate;
import com.pengshun.modules.api.transport.dto.InfoDates;
import com.pengshun.modules.api.transport.dto.TransportDto;
import com.pengshun.modules.api.transport.dto.TransportTakeOrderDto;
import com.pengshun.modules.api.transport.repository.TransportOrderRecordRepository;
import com.pengshun.modules.api.transport.repository.TransportTakeCarriageRepository;
import com.pengshun.modules.api.transport.repository.TransportTakeOrderRepository;
import com.pengshun.modules.api.transport.repository.TransportTakeStatusRepository;
import com.pengshun.modules.api.transport.service.UserTransportService;
import com.pengshun.modules.api.transport.service.mapstruct.TransportTakeOrderTodo;
import com.pengshun.modules.common.BaseResult;
import com.pengshun.modules.common.UserType;
import com.pengshun.modules.domain.*;
import lombok.RequiredArgsConstructor;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.context.MessageSource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

@Service
@RequiredArgsConstructor
public class UserTransportServiceImpl implements UserTransportService {

    private final TransportMapper transportMapper;

    private final TransportTakeCarriageRepository transportTakeCarriageRepository;

    private final TransportTakeOrderRepository transportTakeOrderRepository;

    private final TransportTakeOrderTodo transportTakeOrderDtoTodo;

    private final UserRepository userRepository;

    private final TransportOrderRecordRepository transportOrderRecordRepository;

    private  final MessageSource messageSource;

    private final TransportTakeStatusRepository transportTakeStatusRepository;

    @Override
    public BaseResult userList(TransportDto para) {
        int page = (para.getPage()) * para.getSize();
        if(para.getSort()!=null&&para.getSort()==0){
            para.setSort(null);
        }
        List<TransportDto> list = transportMapper.selectUserListBy(page < 0 ? 0 : page, para.getSize(), para.getSort(), para.getInfoType(), para.getFreightTypeCode(),
                para.getFreightTransportCode(), para.getVehicleTypeId(), para.getVehicleLengthId(), para.getLongitude(), para.getLatitude(), para.getShipProvinceAdcode(),
                para.getShipCityAdcode(), para.getShipDistrictAdcode(), para.getReceiveProvinceAdcode(), para.getReceiveCityAdcode(), para.getReceiveDistrictAdcode(),
                para.getMerchantId(), para.getShowPosition(),para.getName());
        return new BaseResult(0, list);
    }

    @Override
    public BaseResult topInfo(TransportDto para) {
        int page = (para.getPage()) * para.getSize();
        TransportDto dto= transportMapper.selectTopInfo(new Date(), page < 0 ? 0 : page, para.getSize());
        return new BaseResult(dto!=null?0:1,dto);
    }

    @Override
    public BaseResult detil(TransportDto para) throws Exception {
        TransportDto dto = transportMapper.getTransportDetilById(para.getId());
        List<InfoDates> dates = new ArrayList<>();
        BigDecimal price = dto.getFreightPrice();
//        if (dto.getInfoType() == 0) {
//            price = new BigDecimal(0);
//        }
        if (dto.getIsPremium() != null && dto.getIsPremium() == 1) {
            price = dto.getPremiumPrice();
            //判断当前时间和开始时间
            Long nowTime = System.currentTimeMillis();
            SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss");
            String s = format.format(dto.getStartGrabSingle());
            String d = format.format(dto.getEndGrabSingle());
            String n = format.format(new Date());
            dto.setStartTime(s);
            dto.setEndTime(d);
            Date str = format.parse(s);
            Date end = format.parse(d);
            Date now = format.parse(n);

            if (nowTime < dto.getStartGrabSingle().getTime()) {
                //距离开始多久时间
                dto.setState(1);
                dto.setTime((now.getTime() - str.getTime()) / 1000 + "");
            } else if (nowTime > dto.getEndGrabSingle().getTime()) {
                //说明已经结束
                dto.setState(3);
                dto.setIsPremium(0);
            } else {
                //距离多久结束
                dto.setState(2);
                long t = end.getTime();
                long a = now.getTime();
                long tt = (t - a) / 1000;

                dto.setTime(tt + "");
            }
        }
        dto.setTransportStartTime(dto.getStartDate());
        dto.setTransportEndTime(dto.getEndDate());
        dates = getDates(dto.getStartDate(), dto.getEndDate(), price);
        dto.setDates(dates);
        List<InfoDate> basedates = new ArrayList<>();
        int i = 0;
        for (InfoDates da : dates) {
            for (InfoDate d : da.getDates()) {
                InfoDate date=new InfoDate(d.getDate(),d.getDay(),d.getPrice() == null ? "--" : d.getPrice(),d.getPrice() == null ? false : true, true);
                if (d.getIscheck()) {
//                    d.setContent("今天");
//                    d.setIscheck(d.getPrice() == null ? false : d.getIscheck());
//                    d.setPrice(d.getPrice() == null ? "--" : d.getPrice());
//                    InfoDate date=new InfoDate(d.getPrice() == null ? "--" : d.getPrice(),d.getPrice() == null ? false : true,"今天",false);
                    date.setContent("今天");
                    basedates.add(date);
                    i++;
                } else if (i == 1&&d.getDay()!=null) {
//                    d.setContent("明天");
//                    d.setIscheck(d.getPrice() == null ? false : d.getIscheck());
//                    d.setPrice(d.getPrice() == null ? "--" : d.getPrice());
                    date.setDisable(d.getPrice()!=null?true:false);
                    date.setContent("明天");
                    basedates.add(date);
                    i++;
                } else if (i == 2&&d.getDay()!=null) {
//                    InfoDate date=new InfoDate(d.getPrice() == null ? "--" : d.getPrice(),d.getPrice() == null ? false : true,"后天",false);
                    date.setDisable(d.getPrice()!=null?true:false);
                    date.setContent("后天");

                    basedates.add(date);
                    i++;
                }
//                if (i > 0&&d.getDay()!=null) {
//                    i++;
//                }
            }
        }
        SimpleDateFormat f = new SimpleDateFormat("yyyy/MM/dd");
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        if (basedates.size() == 0) {
            basedates.add(new InfoDate("", "今天", "--"));
            basedates.add(new InfoDate("", "明天", "--"));
            basedates.add(new InfoDate("", "后天", "--"));
            basedates.add(new InfoDate("", "----/--/--", "--"));
        }
        if (basedates.size() == 1) {
            basedates.add(new InfoDate("", "明天", "--"));
            basedates.add(new InfoDate("", "后天", "--"));
            basedates.add(new InfoDate(df.format(new Date()), f.format(new Date()), basedates.get(0).getPrice()));

        }
        if (basedates.size() == 2) {
            basedates.add(new InfoDate("", "后天", "--"));
            basedates.add(new InfoDate(df.format(new Date()), f.format(new Date()), basedates.get(0).getPrice()));
        }
        if (basedates.size() == 3) {
            basedates.add(new InfoDate(df.format(new Date()), f.format(new Date()), basedates.get(0).getPrice()));
        }
        for (InfoDate basedate : basedates) {
            basedate.setPrice(basedate.getPrice() == null ? "--" : basedate.getPrice());
        }

        dto.setInfoDates(basedates);
        if (dto.getInfoFee() == null) {
            dto.setInfoFee(new BigDecimal(0));
        }
        dto.setInfoFee(dto.getInfoFee() == null ? new BigDecimal(0) : dto.getInfoFee());
        dto.setLoadFee(dto.getLoadFee() == null ? new BigDecimal(0) : dto.getLoadFee());
        dto.setUnloadFee(dto.getUnloadFee() == null ? new BigDecimal(0) : dto.getUnloadFee());
        dto.setPoundsFee(dto.getPoundsFee() == null ? new BigDecimal(0) : dto.getPoundsFee());
        dto.setOtherFee(dto.getOtherFee() == null ? new BigDecimal(0) : dto.getOtherFee());
        return new BaseResult(0, dto);

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public BaseResult takeOrder(TransportTakeOrderDto para) throws Exception {
        User user = userRepository.findById(para.getUserId()).orElseGet(User::new);
        if (user.getStatus() != 2) {
            return new BaseResult(1, messageSource.getMessage("UserTransportServiceImpl.takeOrder.getUserId", null, Locale.CHINA));
        }
        //判断用户类型   车主 司机 运输公司可以接单
        Integer istake=transportMapper.findUserTake(user.getUserType());
        if(istake==null||istake==0){
            return new BaseResult(1, messageSource.getMessage("UserTransportServiceImpl.takeOrder.no", null, Locale.CHINA));
        }
        //如果角色是司机 判断当前车辆有没有未完成的运单
        if(user.getUserType().equals(UserType.ONE_STATUS)){
            //判断车辆是否运输中
            Integer inTransport=transportMapper.findInTransportByCarnum(para.getCarOwnerNum());
            if(inTransport!=null&inTransport>0){
                return new BaseResult(1, messageSource.getMessage("UserTransportServiceImpl.takeOrder.car", null, Locale.CHINA));
            }
            //判断接单人是否有运输中的货运
            Integer inTransports=transportMapper.findInTransportByUserId(para.getUserId());
            if(inTransports!=null&inTransports>0){
                return new BaseResult(1, messageSource.getMessage("UserTransportServiceImpl.takeOrder.fail", null, Locale.CHINA));
            }
        }

        //判断用户车辆总共承载量  接取数量不能超过总载重
//        BigDecimal canTakeNum=transportMapper.canTakeNum(para.getCarOwnerId());
        BigDecimal canTakeNum=new BigDecimal(150);
        if(para.getNumber().compareTo(canTakeNum)==1){
            return new BaseResult(1, messageSource.getMessage("UserTransportServiceImpl.takeOrder.carload", null, Locale.CHINA));
        }
        //判断库存数量
        TransportDto dto = transportMapper.getTransportDetilById(para.getTransportId());
        //收款人不能接自己发布的货运
        if(dto.getUserId().equals(para.getUserId())){
            return new BaseResult(1, messageSource.getMessage("UserTransportServiceImpl.takeOrder.same", null, Locale.CHINA));
        }
        //货运剩余数量
        BigDecimal num = dto.getTotalNumber();
        if (num.compareTo(para.getNumber()) == -1) {
            return new BaseResult(1, messageSource.getMessage("UserTransportServiceImpl.takeOrder.refresh", null, Locale.CHINA));
        }
        if (para.getInfoFee().compareTo(dto.getInfoFee()) != 0) {
            return new BaseResult(1, messageSource.getMessage("UserTransportServiceImpl.takeOrder.message", null, Locale.CHINA));
        }
        if (para.getFreight().compareTo(dto.getFreightPrice()) != 0) {
            return new BaseResult(1, messageSource.getMessage("UserTransportServiceImpl.takeOrder.getFreightPrice", null, Locale.CHINA));
        }
        if (para.getLoadFee().compareTo(dto.getLoadFee()) != 0) {
            return new BaseResult(1, messageSource.getMessage("UserTransportServiceImpl.takeOrder.getLoadFee", null, Locale.CHINA));
        }
        if (para.getUnloadFee().compareTo(dto.getUnloadFee()) != 0) {
            return new BaseResult(1, messageSource.getMessage("UserTransportServiceImpl.takeOrder.getUnloadFee", null, Locale.CHINA));
        }
        if (para.getPoundsFee().compareTo(dto.getPoundsFee()) != 0) {
            return new BaseResult(1, messageSource.getMessage("UserTransportServiceImpl.takeOrder.getPoundsFee", null, Locale.CHINA));
        }
        if (para.getOtherFee().compareTo(dto.getOtherFee()) != 0) {
            return new BaseResult(1, messageSource.getMessage("UserTransportServiceImpl.takeOrder.getOtherFee", null, Locale.CHINA));
        }

        //判断运费是否计算正确
        BigDecimal totalFee = para.getNumber().multiply(para.getFreight());
        if (totalFee.compareTo(para.getTotalFreight()) != 0) {
            return new BaseResult(1,  messageSource.getMessage("UserTransportServiceImpl.takeOrder.getTotalFreight", null, Locale.CHINA));
        }

        para.setTakeOrderType(user.getUserType());
        if (user.getUserType() == 3) {
            para.setTransportCompanyId(user.getMerchantId());
            para.setTransportCompanyName(user.getMerchantName());
        }

        if (user.getUserType() == 2) {
            para.setOwnerUserId(user.getId());
        }


        para.setTransportTakeNo(dto.getTransportNo());
        para.setStatus(1);
        para.setType(1);
        para.setTotalNumber(para.getNumber());
        para.setTakeTime(new Date());
        para.setOrderId(dto.getOrderId());
        User grantUser=userRepository.findById(para.getGatheringUserId()).orElseGet(User::new);
        para.setGatheringUserName(grantUser.getName());
        para.setGatheringUserPhone(grantUser.getPhone());
        TransportTakeOrder order = transportTakeOrderRepository.save(transportTakeOrderDtoTodo.toEntity(para));
        if (user.getUserType() == 1) {
            String no = "PTT" + CommonUtil.getFourRandom();
            TransportTakeCarriage carriage = transportTakeCarriageRepository.save(new TransportTakeCarriage(order.getTransportTakeOrderId(),user.getName(), para.getUserId(), no, 1,
                    para.getCarOwnerId(), para.getCarOwnerNum(), para.getCarTypeName(), para.getNumber(), new Date(), dto.getFreightPrice(), dto.getInfoFee(),
                    dto.getLoadFee(), dto.getUnloadFee(), dto.getPoundsFee(), dto.getOtherFee(),0,dto.getOrderId(),1,dto.getTakeType()));
            carriage.setAllotUserId(para.getUserId());
            TransportOrderRecord transportOrderRecord = new TransportOrderRecord(para.getTransportId(), carriage.getTransportTakeCarriageId(), order.getOrderId(), para.getUserId(), 1);
            transportOrderRecordRepository.save(transportOrderRecord);
            //流程保存
            TransportTakeStatus status= new TransportTakeStatus();
            status.setTakeTime(new Date());
            status.setTransportTakeCarriageId( carriage.getTransportTakeCarriageId());
            transportTakeStatusRepository.save(status);
            //todo 信息费收取
        }
        //减库存
        BigDecimal nowCoalNumber = dto.getTotalNumber().subtract(para.getNumber());
        BigDecimal oldCoalNumber = dto.getTotalNumber();
        transportMapper.updateTransportWeight(dto.getId(), nowCoalNumber, oldCoalNumber);
        return new BaseResult(0);
    }

    private List<InfoDates> getDates(Date start, Date end, BigDecimal price) throws Exception {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        SimpleDateFormat format1 = new SimpleDateFormat("yyyy-MM");
        SimpleDateFormat format2 = new SimpleDateFormat("yyyy年MM月");
        SimpleDateFormat format0 = new SimpleDateFormat("yyyyMMdd");
        List<InfoDates> dates = new ArrayList<>();
        List<InfoDate> strings = getDayByMonth(start);
        //补全开始数据
        int week = getWeek(strings.get(0).getDate()) - 1;
        for (int i = 0; i < week; i++) {
            strings.add(i, new InfoDate(i + "", null, "prices", false, false));
        }
        dates.add(new InfoDates(format2.format(start), strings));

        if (!format1.format(start).equals(format1.format(end))) {
            List<InfoDate> strings1 = getDayByMonth(end);
            int weeks = getWeek(strings1.get(0).getDate()) - 1;
            for (int i = 0; i < weeks; i++) {
                strings1.add(i, new InfoDate(i + "", null, "prices", false, false));
            }
            dates.add(new InfoDates(format2.format(end), strings1));
        }
        //当前时间格式
        Integer now = Integer.parseInt(format0.format(new Date()));
        //开始时间格式
        Integer star = Integer.parseInt(format0.format(start));
        //结束时间格式
        Integer en = Integer.parseInt(format0.format(end));
        //
        String prices = null;
        for (InfoDates infoDates : dates) {

            for (InfoDate info : infoDates.getDates()) {
                if (info.getDay() == null) {
                    continue;
                }
                Boolean disable = false;
                //设置选中时间
                String d = format.format(new Date());
                Boolean check = d.equals(info.getDate());
                info.setIscheck(check);

                Integer da = Integer.parseInt(format0.format(format.parse(info.getDate())));
                //填充价格
                if (star.equals(da)) {
                    prices = price.stripTrailingZeros().toPlainString();
                }
                if (da > en) {
                    prices = null;
                }
                //日期在开始结束日期之间并且大于等于当前时间的可以点击
                if(da>=star&&en>=da&&da>=now){
                    disable = true;
                }
                info.setPrice(prices);
                info.setDisable(disable);
            }
        }
        return dates;
    }

    private int getWeek(String date) throws ParseException {
        SimpleDateFormat formater = new SimpleDateFormat("yyyy-MM-dd");
        Calendar c = Calendar.getInstance();
        Date dates = formater.parse(date);
        c.setTime(dates);
        int dayForWeek = 0;
        if (c.get(Calendar.DAY_OF_WEEK) == 1) {
            dayForWeek = 7;
        } else {
            dayForWeek = c.get(Calendar.DAY_OF_WEEK) - 1;
        }
        return dayForWeek;
    }

    public List<InfoDate> getDayByMonth(Date date) {
        List<InfoDate> list = new ArrayList();
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");

        SimpleDateFormat format1 = new SimpleDateFormat("yyyy");
        SimpleDateFormat format2 = new SimpleDateFormat("MM");
        Calendar aCalendar = Calendar.getInstance(Locale.CHINA);
        aCalendar.set(Integer.parseInt(format1.format(date)), Integer.parseInt(format2.format(date)), 0);
        int year = aCalendar.get(Calendar.YEAR);//年份
        int month = aCalendar.get(Calendar.MONTH) + 1;//月份
        int day = aCalendar.getActualMaximum(Calendar.DATE);
        for (int i = 1; i <= day; i++) {
            String aDate = null;
            if (month < 10 && i < 10) {
                aDate = String.valueOf(year) + "-0" + month + "-0" + i;
            }
            if (month < 10 && i >= 10) {
                aDate = String.valueOf(year) + "-0" + month + "-" + i;
            }
            if (month >= 10 && i < 10) {
                aDate = String.valueOf(year) + "-" + month + "-0" + i;
            }
            if (month >= 10 && i >= 10) {
                aDate = String.valueOf(year) + "-" + month + "-" + i;
            }

            list.add(new InfoDate(aDate, i, "prices", false, false));
        }
        return list;
    }
}
